/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.wikimark.container;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.security.Principal;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.wikimark.http.AbstractPostRequest;
import org.apache.wikimark.http.XFormPostRequest;

final class HttpServletRequestImpl implements HttpServletRequest {
	private final URL url;	
	private final Map<String, String[]> params = new HashMap<String, String[]>();
	private final HttpSessionImpl session;	
	private final Map<String, Object> attrs = new HashMap<String, Object>();
	private final AbstractPostRequest content;
	
	private final Map<String, Object> headers = new HashMap<String, Object>();
		
	private String encoding = "utf-8";
	
	HttpServletRequestImpl(HttpSessionImpl session, URL url, AbstractPostRequest request) {
		this.url = url;
		this.session = session;
		this.content = request != null ? request : new XFormPostRequest("");
		
		headers.put("USER_AGENT", "WikiMark");
	}

	public String getAuthType() {
		return null;
	}

	public String getContextPath() {
		return "/";
	}

	public Cookie[] getCookies() {
		return session.cookies.values().toArray(new Cookie[session.cookies.size()]);
	}

	public long getDateHeader(String name) {
		return 0;
	}

	public String getHeader(String name) {
		if (name.equals("Content-Type")) {
			return getContent().getContentType();
		}
		return (String)headers.get(name);
	}

	public Enumeration<String> getHeaderNames() {
		return Collections.enumeration(headers.keySet());			
	}

	public Enumeration<String> getHeaders(String name) {
		List<String> empty = Collections.emptyList();
		return Collections.enumeration(empty);			
	}

	public int getIntHeader(String name) {
		return 0;
	}

	public String getMethod() {
		return "POST";
	}

	public String getPathInfo() {
		return content.getPathInfo();
	}

	public String getPathTranslated() {
		return url.getPath();
	}

	public String getQueryString() {		
		return url.getQuery();
	}

	public String getRemoteUser() {
		return null;
	}

	public String getRequestURI() {
		return url.getFile();
	}

	public StringBuffer getRequestURL() {
		StringBuffer buf = new StringBuffer();
		return buf.append(getScheme()).append("://").append(getServerName())
				.append(getRequestURI());
	}

	public String getRequestedSessionId() {
		return isRequestedSessionIdValid() ? getSession(false).getId() : null;
	}

	public String getServletPath() {
		String path = url.getPath(); 
		int index = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
		return path.substring(Math.max(0, index));
	}

	public HttpSession getSession() {
		return getSession(true);
	}

	public HttpSession getSession(boolean create) {
		return session;
	}

	public Principal getUserPrincipal() {
		return null;
	}

	public boolean isRequestedSessionIdFromCookie() {
		return true;
	}

	public boolean isRequestedSessionIdFromURL() {
		return false;
	}

	public boolean isRequestedSessionIdFromUrl() {
		return isRequestedSessionIdFromURL();
	}

	public boolean isRequestedSessionIdValid() {
		return getSession(false) != null;
	}

	public boolean isUserInRole(String role) {
		return false;
	}

	public Object getAttribute(String name) {
		return attrs.get(name);
	}

	public Enumeration<String> getAttributeNames() {
		return Collections.enumeration(attrs.keySet());
	}

	public String getCharacterEncoding() {
		return encoding;
	}

	public int getContentLength() {
		return getContent().getContentString().length();
	}

	public String getContentType() {
		return getContent().getContentType();
	}

	public ServletInputStream getInputStream() throws IOException {
		return new ServletInputStream() {
			final String content = getContent().getContentString();
			int cursor;
			@Override
			public int read() throws IOException {
				return cursor < content.length() ? content.charAt(cursor++) : -1;
			}
			
		};
	}

	public String getLocalAddr() {
		return "127.0.0.1";
	}

	public String getLocalName() {
		return "localhost";
	}

	public int getLocalPort() {
		return 80;
	}

	public Locale getLocale() {
		return Locale.getDefault();
	}

	public Enumeration<Locale> getLocales() {
		return null;
	}

	public String getParameter(String name) {
		String[] row = params.get(name);
		return row != null && row.length > 0 ? row[0] : null;
	}

	public Map<String, String[]> getParameterMap() {
		return params;
	}

	public Enumeration<String> getParameterNames() {
		return Collections.enumeration(params.keySet());
	}

	public String[] getParameterValues(String name) {
		return params.get(name);
	}

	public String getProtocol() {
		return "HTTP/1.1";
	}

	public BufferedReader getReader() throws IOException, IllegalStateException {		
		return new BufferedReader(new StringReader(getContent().getContentString()));
	}

	public String getRealPath(String uri) {
		return url.getPath();
	}

	public String getRemoteAddr() {
		return "127.0.0.1";
	}

	public String getRemoteHost() {
		return "localhost";
	}

	public int getRemotePort() {
		return 1;
	}

	public RequestDispatcher getRequestDispatcher(String uri) {
		throw new UnsupportedOperationException("not implemented");
	}

	public String getScheme() {		
		return "http";
	}

	public String getServerName() {
		return "localhost";
	}

	public int getServerPort() {
		return 80;
	}

	public boolean isSecure() {
		return false;
	}

	public void removeAttribute(String name) {
		attrs.remove(name);
	}

	public void setAttribute(String name, Object o) {
		attrs.put(name, o);
	}

	public void setCharacterEncoding(String encoding)
			throws UnsupportedEncodingException {
		this.encoding = encoding; 
	}
	
	private AbstractPostRequest getContent() {
		return content;
	}

}
